package com.common.frame.base


import android.content.DialogInterface
import android.graphics.drawable.ColorDrawable
import android.os.Build
import android.os.Bundle
import android.view.*
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.LifecycleOwner
import com.common.frame.R
import com.common.frame.lifecycle.ActivityManager
import com.common.frame.utils.ScreenUtil

abstract class BaseDialogFragment<VB : ViewDataBinding> : DialogFragment(), View.OnClickListener {

    lateinit var binding: VB

    var dismissDialog: (() -> Unit)? = null

    fun getDialogArgument(): Bundle {
        return arguments ?: Bundle().apply {
            arguments = this
        }
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        isCancelable = cancelable()
        dialog?.window?.also { window ->
            if (isCancelable) {
                window.setBackgroundDrawable(ColorDrawable())
            }
            if (getAnimation() != -1) {
                window.setWindowAnimations(getAnimation())
            }
            if (!fitsSystemWindows()) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                    window.attributes?.layoutInDisplayCutoutMode =
                        WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
                    window.decorView.systemUiVisibility =
                        View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                }
                ViewCompat.setOnApplyWindowInsetsListener(window.decorView) { _, insets ->
                    val inset = insets.getInsets(WindowInsetsCompat.Type.systemBars())
                    binding.root.setPadding(inset.left, 0, inset.right, inset.bottom)
                    WindowInsetsCompat.CONSUMED
                }
            }
            window.attributes?.apply {
                gravity = getGravity()
                width = getWidth() - getMargin()
                height = getHeight()
                if (hideBackgroundShadow()) {
                    dimAmount = 0f
                }
            }
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = DataBindingUtil.inflate(inflater, getLayoutId(), null, false)


        initView()
        initListener()
        initViewObservable()


        return binding.root
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setStyle(
            STYLE_NO_TITLE,
            if (fitsSystemWindows()) R.style.BaseCustomDialog else R.style.DialogFullScreen
        )
    }

    abstract fun getLayoutId(): Int

    abstract fun initView()

    open fun initListener() {}

    open fun initViewObservable() {}

    override fun onClick(v: View) {

    }

    open fun getGravity(): Int = Gravity.CENTER

    open fun getWidth(): Int = ScreenUtil.getScreenWidth(requireContext())

    open fun getHeight(): Int = WindowManager.LayoutParams.WRAP_CONTENT

    open fun cancelable(): Boolean = true

    /**
     * false是沉浸式  true:不沉浸式
     */
    open fun fitsSystemWindows(): Boolean = true

    open fun hideBackgroundShadow(): Boolean = false

    open fun getMargin(): Int = 0

    open fun getAnimation(): Int = -1

    fun show(context: LifecycleOwner?, tag: String? = this::class.java.simpleName) {
        when (context) {
            is FragmentActivity -> show(context.supportFragmentManager, tag)
            is Fragment -> show(context.childFragmentManager, tag)
            else -> show(ActivityManager.getCurrentActivity() as FragmentActivity, tag)
        }
    }

    override fun show(manager: FragmentManager, tag: String?) {
        showAllowingStateLoss(manager, tag)
    }


    private fun showAllowingStateLoss(manager: FragmentManager, tag: String?) {
        try {
            val dismissed = DialogFragment::class.java.getDeclaredField("mDismissed")
            dismissed.isAccessible = true
            dismissed.set(this, false)
        } catch (e: NoSuchFieldException) {
            e.printStackTrace()
        } catch (e: IllegalAccessException) {
            e.printStackTrace()
        }
        try {
            val shown = DialogFragment::class.java.getDeclaredField("mShownByMe")
            shown.isAccessible = true
            shown.set(this, true)
        } catch (e: NoSuchFieldException) {
            e.printStackTrace()
        } catch (e: IllegalAccessException) {
            e.printStackTrace()
        }
        val ft = manager.beginTransaction()
        ft.add(this, tag)
        ft.commitAllowingStateLoss()
    }

    override fun onDismiss(dialog: DialogInterface) {
        super.onDismiss(dialog)
        dismissDialog?.invoke()
    }

    override fun dismissAllowingStateLoss() {
        try {
            super.dismissAllowingStateLoss()
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
        }
    }

}

